/**
 * $Id$
 *
 * Copyright (c) 2014 ChinaSoft International, Ltd. All rights reserved
 * JointForce Project
 *
 */
package com.csi.jf.crucible.api.crucible;

import java.io.IOException;
import java.util.Iterator;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.chinasofti.ro.bizframework.modules.json.JSONArray;
import com.chinasofti.ro.bizframework.modules.json.JSONObject;
import com.icss.j2ee.util.http.HttpClientException;

/**
 * @Title: RestAPITest.java
 * @Description: <br>
 *               <br>
 * @Company: Chinasofti
 * @Created on 2014-6-20 下午4:31:56
 * @author zhangmh
 * @version $Revision: 1.0 $
 * @since 1.0
 */
public class RestAPITest {
    
    private static final String HOST = "http://115.29.76.124:8060";
    private static final String AUTH_URL = "FEAUTH=zhangmh:4:31b8dd8276ef06615e0b8b3018c78f45";
    //private static final String CRUCIBLE_AUTH_TOKEN = "FEAUTH=zhangmh:2:d249481bd97fc34edc6e855731168517";

    public static void main(String[] args) throws Exception{
        RestAPITest t = new RestAPITest();
        //t.getLoginToken("zhangmh","123456");
//        t.addUser();
//        t.addRepositories();
        t.testProjectAdminApi();
//        String projectName = "testproject";
//        t.isExistProject(projectName);
    }
    
    
    public void testProjectAdminApi() throws HttpClientException, IOException{
        String key = "newkey";
        String name = "newproject";
        //create project
        //name={projectName}&key={projectKey}&defaultRepositoryName={defaultRepoName}&storeRevisions={true/false}&permissionSchemeName={permissionScheme}&moderatorEnabled={true/false}&defaultModerator={defaultModerator}&defaultDuration={defaultDuration}&defaultObjectives={defaultObjective}
        String param="name="+name+"&key="+key+"&defaultRepositoryName=CrucibleTest&storeRevisions=true&permissionSchemeName=agile&moderatorEnabled=true&defaultModerator=zhaochen&defaultDuration=8&defaultObjectives=do-new-review&";
        String url = HOST + "/rest/project-admin/latest/project-new?"+param+AUTH_URL;
        this.doGet(url);
        /*
         * {
                "response": {
                    "code": "200", 
                    "message": "operation succeeded", 
                    "cause": ""
                }
            }
         */
        
        //update project
        //"name={projectName}&key={projectKey}&defaultRepositoryName={defaultRepoName}&storeRevisions={true/false}&permissionSchemeName={permissionScheme}&moderatorEnabled={true/false}&defaultModerator={defaultModerator}&defaultDuration={defaultDuration}&defaultObjectives={defaultObjective}";
        param="name="+name+"&key="+key+"&defaultRepositoryName=CrucibleTest&storeRevisions=true&permissionSchemeName=agile&moderatorEnabled=true&defaultModerator=zhangmh&defaultDuration=5&defaultObjectives=do-test-review&";
        url = HOST + "/rest/project-admin/latest/project-update?"+param+AUTH_URL;
        this.doGet(url);
        /*
         * {
                "response": {
                    "code": "200", 
                    "message": "operation succeeded", 
                    "cause": ""
                }
            }
         */
        
        //list project
        url = HOST + "/rest/project-admin/latest/project-list?"+AUTH_URL;
        this.doGet(url);
        /*
        {
            "response": {
                "code": "200", 
                "message": "operation succeeded", 
                "cause": ""
            }, 
            "projectList": [
                {
                    "name": "Default Project", 
                    "key": "CR", 
                    "storeRevisions": true, 
                    "permissionSchemeId": 2, 
                    "moderatorEnabled": true, 
                    "defaultDuration": 5
                }, 
                {
                    "name": "PtsTestProject", 
                    "key": "PTS-TEST", 
                    "defaultRepositoryName": "CrucibleTest", 
                    "storeRevisions": true, 
                    "permissionSchemeId": 2, 
                    "moderatorEnabled": true, 
                    "defaultModerator": "zhangmh", 
                    "defaultDuration": 7, 
                    "defaultObjectives": ""
                }
            ]
        }
        */
        
        //delete project
        //http://crucible.mycompany.com/rest/project-admin/latest/project-delete?key=MNP
        url = HOST + "/rest/project-admin/latest/project-delete?key="+key+"&"+AUTH_URL;
        this.doGet(url);
        /*
         * {
                "response": {
                    "code": "200", 
                    "message": "operation succeeded", 
                    "cause": ""
                }
            }
         */
    }
    
    /**
     * @param type - SUBVERSION, PERFORCE, GIT, HG, CVS
       @param name - repository name
       @param SONAR_URL - svn SONAR_URL, perforce host, git/hg location, cvs dir
       @param path - svn/perforce/git/hg path [optional]
       @param description - repository description [optional]
       @param username - svn/perforce username [optional]
       @param password - svn/perforce/git/hg password [optional]
       @return
       
     * @throws Exception
     */
    public void addRepositories()throws Exception{
        //Adds repository
        String url = "/rest-service-fecru/admin/repositories-v1?type=GIT&name=JFPts&SONAR_URL=https://zhangmh%40chinasofti.com@git.jointforce.com/scm/join/jfpts.git&username=zhangmh&password=zhangmh2013&"+AUTH_URL;
        this.doGet(url);
    }
//
//    public void createProject()throws Exception{
//        //Adds repository
//        String SONAR_URL = "/rest-service-fecru/project-admin/latest/project-new?name=JfPts0703&key=PTS&defaultRepositoryName=CrucibleTest&storeRevisions=true&permissionSchemeName=agile&moderatorEnabled=true&defaultModerator=admin&defaultDuration=145&defaultObjectives=MyObjective&SONAR_URL=https://zhangmh%40chinasofti.com@git.jointforce.com/scm/join/jfpts0703.git&username=zhangmh&password=zhangmh2013&"+AUTH_URL;
//        this.doGet(SONAR_URL);
//    }
    
    /**
     * @param {repo} string repository-name
     * @return
     *{
        "name": "CrucibleTest", 
        "state": "RUNNING", 
        "enabled": true, 
        "indexingStatus": {
            "linesOfContentIndexingInProgress": false, 
            "crossRepositoryRescanInProgress": false, 
            "error": false, 
            "fullIndexingInProgress": false, 
            "initialScanningComplete": true, 
            "lastScanTime": 1403839447809, 
            "incrementalIndexingInProgress": false, 
            "fullRepositorySlurpDone": true, 
            "indexingStateCounts": {
                "INFILLED": 0, 
                "COMPLETE": 0, 
                "METADATA_INDEXED": 0, 
                "SCANNED": 0, 
                "CONTENT_INDEXED": 0, 
                "UNKNOWN": 3
            }
        }
     }
     */
    public void getRepositoryStatus()throws Exception{
        String url = "/rest-service-fecru/admin/repositories-v1/CrucibleTest?"+AUTH_URL;
        this.doGet(url);
    }
    
    /**
     *@param type string filter users by authentication type: built-in, LDAP, host, custom, ajp, crowd
     *@param crucible boolean filter users by crucible flag
     *@return:
     {
        "start": 0, 
        "limit": 100, 
        "lastPage": true, 
        "size": 4, 
        "values": [
            {
                "name": "duanhui", 
                "displayName": "duan hui", 
                "email": "duanhui@chinasofti.com", 
                "type": "crowd", 
                "crucible": true
            }, 
            {
                "name": "fenghaibing", 
                "displayName": "feng haibing", 
                "email": "fenghaibing@chinasofti.com", 
                "type": "crowd", 
                "crucible": true
            }, 
            {
                "name": "maogx", 
                "displayName": "mao gx", 
                "email": "maogx@chinasofti.com", 
                "type": "crowd", 
                "crucible": true
            }, 
            {
                "name": "zhangmh", 
                "displayName": "daniel zang", 
                "email": "zhangmh_hunu@126.com", 
                "type": "crowd", 
                "crucible": true
            }
        ]
     }
     */
    public void getAdminUser() throws Exception{
        String url = "/rest-service-fecru/admin/users?type=crowd&crucible=true&"+AUTH_URL;
        //for test
        this.doGet(url);
    }
    
    public void addUser() throws Exception{
        //type=built-in&crucible=false&
        String url = "/rest-service-fecru/admin/users?type=built-in&crucible=false&"+AUTH_URL;
        /*{
        "name" : "newkash",
        "password" : "1234",
        "displayName" : "Lukasz Kuzynski",
        "email" : "newkash@atlassian.com",
        "type" : "built-in",
        "crucible" : true
          }*/
        String json = "{\"name\" : \"newkash\",\"password\" : \"123456\",\"displayName\" : \"Lukasz Kuzynski\",\"email\" : \"newkash@atlassian.com\",\"type\" : \"built-in\",\"crucible\" : true}";
        this.doPost(url,json);
    }
    
    /**
     @param type string filter groups by authentication type: built-in, LDAP, host, custom, ajp, crowd, ...
     @param admin boolean filter groups by admin flag
     @param prefix string filter groups by name prefix
     @return
     {
        "start": 0, 
        "limit": 100, 
        "lastPage": true, 
        "size": 1, 
        "values": [
            {
                "name": "crucible-administrators", 
                "types": [
                    "crowd"
                ], 
                "admin": true
            }
        ]
     }
     @return
     {
        "start": 0, 
        "limit": 100, 
        "lastPage": true, 
        "size": 10, 
        "values": [
            {
                "name": "confluence-administrators", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "confluence-users", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "crowd-administrators", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "crowd-users", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "crucible-users", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "jira-administrators", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "jira-developers", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "jira-users", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "sonar-administrators", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }, 
            {
                "name": "sonar-users", 
                "types": [
                    "crowd"
                ], 
                "admin": false
            }
        ]
    }
     * @throws Exception
     */
    public void adminGroups()throws Exception{
        //Retrieve a page of groups.
        String url = "/rest-service-fecru/admin/groups?type=crowd&admin=false&prefix=&"+AUTH_URL;
        //this.doGet(SONAR_URL);
        
        //Creates a new built-in group.
        String newGroupName = "team-6";
        url = "/rest-service-fecru/admin/groups?"+AUTH_URL;
        String json = "{\"name\" : \""+newGroupName+"\",\"types\" : [ \"built-in\" ],\"admin\" : true}";
        this.doPost(url,json);
        
        //Retrieve a group by name.
        //{"name":"crucible-users","types":["built-in","crowd"],"admin":false}
        url = "/rest-service-fecru/admin/groups/"+newGroupName+"?"+AUTH_URL;;
        //this.doGet(SONAR_URL);
        
        //Updates an existing group.
        url = "/rest-service-fecru/admin/groups/"+newGroupName+"?"+AUTH_URL;
        json = "{\"admin\" : false}";
        //this.doPut(SONAR_URL,json);
        
        //Deletes a group by name
        url = "/rest-service-fecru/admin/groups/"+newGroupName+"?"+AUTH_URL;
        //this.doDelete(SONAR_URL);
    }
    
    /**
     * @param string username
     * @param string password
     * @return
     *{
     *  "token":"zhangmh:2:d249481bd97fc34edc6e855731168517"
     * }
     * @throws Exception
     */
    public void getLoginToken(String username,String password)throws Exception{
        String url = "/rest-service/auth-v1/login?userName="+username+"&password="+password;
        this.doGet(url);
    }
    
    /**
     {
        "userData": [
            {
                "userName": "zhangmh", 
                "displayName": "daniel zang", 
                "avatarUrl": "http://daniel-pc:8060/avatar/zhangmh?s=48", 
                "SONAR_URL": "/user/zhangmh"
            }
        ], 
        "errors": { }
     }
     * @throws Exception
     */
    public void users_v1() throws Exception{
        String url = "/rest-service/users-v1?username=zhangmh&"+AUTH_URL;
        this.doGet(url);
    }
    
    /**
     * <p>发送HTTP GEt请求</p>
     * @param SONAR_URL
     * @throws HttpClientException
     * @throws IOException
     */
    private String doGet(String url) throws HttpClientException, IOException{
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            if(url!=null && !url.startsWith("http")){
                url = HOST + url;
            }
            HttpGet httpGet = new HttpGet(url);
            System.out.println("****************************************************\n");
            System.out.println("do get request for:\n"+url);
            
            //add authentication info
            //String user = Base64.encode("zhangmh".getBytes());
            //String pass = Base64.encode("8820320".getBytes());
            httpGet.setHeader("Accept","application/json");
            //httpGet.setHeader("Authorization", "Basic."+user+":"+pass);
            
            CloseableHttpResponse response1 = httpclient.execute(httpGet);
            response1.addHeader("content-type", "application/json");
            response1.addHeader("accept", "application/json");
            
//            StringBuilder sb = new StringBuilder();
            try {
                System.out.println(response1.getStatusLine());
                HttpEntity entity1 = response1.getEntity();
//                EntityUtils.consume(entity1);
                String retStr = null;
                if(entity1!=null){
                    retStr = EntityUtils.toString(entity1) ;
//                    BufferedReader reader = new BufferedReader(new InputStreamReader(entity1.getContent()));
//                    String line = null;
//                    while((line=reader.readLine())!=null){
//                        sb.append(line+"\n");
//                    }
//                    reader.close();
//                    System.out.println("Response:"+sb.toString());
                    System.out.println("Response:"+retStr);
                    System.out.println("Length:"+entity1.getContentLength());
                    System.out.println("ContentType:"+entity1.getContentType());
                    System.out.println("Encoding:"+entity1.getContentEncoding());
                    return retStr;
                }
            } finally {
                response1.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return null;
    }
    
    private String doPost(String url,String json) throws HttpClientException, IOException{
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            if(url!=null && !url.startsWith("http")){
                url = HOST + url;
            }
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Accept","application/json");
            System.out.println("****************************************************\n");
            System.out.println("do post request for:\n"+url);
            
//            List <NameValuePair> nvps = new ArrayList <NameValuePair>();
//            nvps.add(new BasicNameValuePair("username", "vip"));
//            nvps.add(new BasicNameValuePair("password", "secret"));
//            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            
            System.out.println("do post data:\n"+json);
            HttpEntity entity = new StringEntity(json);
            httpPost.setEntity(entity);
            
            CloseableHttpResponse response1 = httpclient.execute(httpPost);
            response1.addHeader("content-type", "application/json");
            response1.addHeader("accept", "application/json");
            
            try {
                System.out.println(response1.getStatusLine());
                HttpEntity entity1 = response1.getEntity();
                String retStr = null;
                if(entity1!=null){
                    retStr = EntityUtils.toString(entity1) ;
                    System.out.println("Response:"+retStr);
                    System.out.println("Length:"+entity1.getContentLength());
                    System.out.println("ContentType:"+entity1.getContentType());
                    System.out.println("Encoding:"+entity1.getContentEncoding());
                    return retStr;
                }
            } finally {
                response1.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return null;
    }
    
    private String doDelete(String url) throws HttpClientException, IOException {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            if(url!=null && !url.startsWith("http")){
                url = HOST + url;
            }
            HttpDelete httpDelete = new HttpDelete(url);
            httpDelete.setHeader("Accept","application/json");
            System.out.println("****************************************************\n");
            System.out.println("do delete request for:\n"+url);
            
            CloseableHttpResponse response1 = httpclient.execute(httpDelete);
            response1.addHeader("content-type", "application/json");
            response1.addHeader("accept", "application/json");
            
            try {
                System.out.println(response1.getStatusLine());
                HttpEntity entity1 = response1.getEntity();
                String retStr = null; 
                if(entity1!=null){
                    retStr = EntityUtils.toString(entity1) ;  
                    System.out.println("Response:"+retStr);
                    System.out.println("Length:"+entity1.getContentLength());
                    System.out.println("ContentType:"+entity1.getContentType());
                    System.out.println("Encoding:"+entity1.getContentEncoding());
                    return retStr;
                }
            } finally {
                response1.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return null;
    }

    private String doPut(String url,String json) throws HttpClientException, IOException {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            if(url!=null && !url.startsWith("http")){
                url = HOST + url;
            }
            HttpPut httpPut = new HttpPut(url);
            httpPut.setHeader("Accept","application/json");
            System.out.println("****************************************************\n");
            System.out.println("do put request for:\n"+url);
            
            HttpEntity entity = new StringEntity(json);
            httpPut.setEntity(entity);
            
            CloseableHttpResponse response1 = httpclient.execute(httpPut);
            response1.addHeader("content-type", "application/json");
            response1.addHeader("accept", "application/json");
            
            try {
                System.out.println(response1.getStatusLine());
                HttpEntity entity1 = response1.getEntity();
                String retStr = null;
                if(entity1!=null){
                    retStr = EntityUtils.toString(entity1) ;
                    System.out.println("Response:"+retStr);
                    System.out.println("Length:"+entity1.getContentLength());
                    System.out.println("ContentType:"+entity1.getContentType());
                    System.out.println("Encoding:"+entity1.getContentEncoding());
                    return retStr;
                }
            } finally {
                response1.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpclient.close();
        }
        return null;
    }
}
